import os
import json
import sys
import numpy as np
import cv2
import re
import imageio
import copy
import shapely
from shapely.geometry import Polygon, MultiPoint  #多边形

from tool import utils, imgaug_tool, filesystem, opencv_tool,via_tool # export PYTHONPATH=$PYTHONPATH:`pwd` 


class DataEnhance:

    def __init__(self, cv_image,request_return_image=False, enlarge_mask=False, 
                data_dict=None, flag="polygon",fill_all_row=False,
                convert_to_rect=False, default_label=False):
        """
        @request_return_image:
            是否要求返回裁剪图片, 此模式下 data_dict 里面的标记区域将被填充 每调用一次 将返回一张图片和对应的标签
        @flag:
            "rect" or "polygon"
        """
        self.object_count = 0
        self.label_info = []
        self.region_info = []           # # polygon
        self.crop_images = []           # # 存放裁剪的图片 
        self.polygon_flag = flag        
        self.request_return_image = request_return_image

        self.ori_image = copy.copy(cv_image)
        self.save_image = copy.copy(cv_image)
        self.all_poly_mask = np.zeros(self.ori_image.shape[:2], dtype=np.uint8)
        self._load_data(data_dict,
                        enlarge_mask=enlarge_mask, 
                        fill_all_row=fill_all_row, 
                        convert_to_rect=convert_to_rect,
                        default_label=default_label)
        self.line_height = np.random.randint(20)

    def _load_data(self, data_dict, enlarge_mask=False, fill_all_row=False, convert_to_rect=False, default_label=False):
        if data_dict is None :
            return

        if self.polygon_flag == "polygon":
            xys = via_tool.read_via_poloygon_to_list_imp(data_dict["regions"])

            # # 往车牌图片中贴车牌时, 一个车牌需要两个框, 第二个是外接矩形框
            if convert_to_rect:
                rect_xys = via_tool.read_via_polygon_to_rect_imp(data_dict["regions"], default_label=default_label)
                xys.extend(rect_xys)

        elif self.polygon_flag == "rect":
            xys = via_tool.read_via_rect_to_point_imp(data_dict["regions"])
        else:
            raise NotImplementedError

        for xy, l in xys:
            if self.polygon_flag == "polygon":
                self._update_data([l], [np.array(xy)], 
                                        init_data=True,
                                        enlarge_mask=enlarge_mask, 
                                        fill_all_row=fill_all_row)
            elif self.polygon_flag == "rect":
                self._update_data([l], [np.array([
                                                    [xy[0], xy[1]],
                                                    [xy[2], xy[1]],
                                                    [xy[2], xy[3]],
                                                    [xy[0], xy[3]]
                                                ])], 
                                        init_data=True,
                                        enlarge_mask= enlarge_mask, 
                                        fill_all_row=fill_all_row)
            else:
                raise NotImplementedError

    def convert_to_dict(self, image_path, mask=None,need_aug=None):
        """
        @mask: `array` or `None`
            是否增加水印
        @need_aug： `True` or `False`
            是否需要图像增强
        """
        if mask is not None and np.random.randint(2)==0:
            mask = cv2.resize(mask, self.save_image.shape[:2][::-1])
            alpha = np.random.randint(10, 30) * 0.01
            new_image = self.save_image * (1-alpha) + mask * alpha
            new_image = np.array(new_image, dtype=np.uint8)
        else:
            new_image = self.save_image

        if need_aug:
            new_image, new_region_info, new_label_info = need_aug(new_image, self.region_info, self.label_info)
            # cv2.imwrite(image_path, new_image, [cv2.IMWRITE_JPEG_QUALITY, np.random.randint(65,95)])
            cv2.imwrite(image_path, new_image)

        else:
            new_region_info, new_label_info = self.region_info, self.label_info
            cv2.imwrite(image_path, new_image)

        return_data = dict()
        return_data["filename"] = os.path.basename(image_path)
        regions = []
        for idx in range(len(new_label_info)):

            region = dict()
            region["region_attributes"] = {"label": new_label_info[idx]}
            if self.polygon_flag == "polygon":
                region["shape_attributes"] = {"name": "polygon",
                                                "all_points_x": [int(x[0]) for x in new_region_info[idx]],
                                                "all_points_y": [int(x[1]) for x in new_region_info[idx]]}
            else:
                region["shape_attributes"] = {"name": "rect",
                                                "x": int(np.min(new_region_info[idx][:, 0])),
                                                "y": int(np.min(new_region_info[idx][:, 1])),
                                                "width" : int(np.max(new_region_info[idx][:, 0]) - np.min(new_region_info[idx][:, 0])),
                                                "height" : int(np.max(new_region_info[idx][:, 1]) - np.min(new_region_info[idx][:, 1]))
                                                }  
            regions.append(region)
        return_data["regions"] = regions
        return_data["file_attributes"] = {}
        return return_data

    def convert_to_dict_save_image(self, image_path, need_aug=None):
        """
        @need_aug： `True` or `False`
            是否需要图像增强
        """

        total_data = dict()
        for idx, (img, ri, li) in enumerate(zip(self.crop_images, 
                            self.region_info, 
                            self.label_info)):
            if need_aug:
                new_image, new_region_info, new_label_info = need_aug(img, [ri], [li])
            else:
                new_image, new_region_info, new_label_info = img, [ri], [li]
            
            file_name = image_path.replace(".jpg", "_{}.jpg".format(idx))
            cv2.imwrite(file_name, new_image)

            return_data = dict()
            return_data["filename"] = os.path.basename(file_name)
            regions = []
            for idx in range(len(new_label_info)):

                region = dict()
                region["region_attributes"] = {"label": new_label_info[idx]}
                if self.polygon_flag == "polygon":
                    region["shape_attributes"] = {"name": "polygon",
                                                    "all_points_x": [int(x[0]) for x in new_region_info[idx]],
                                                    "all_points_y": [int(x[1]) for x in new_region_info[idx]]}
                else:
                    region["shape_attributes"] = {"name": "rect",
                                                    "x": int(np.min(new_region_info[idx][:, 0])),
                                                    "y": int(np.min(new_region_info[idx][:, 1])),
                                                    "width" : int(np.max(new_region_info[idx][:, 0]) - np.min(new_region_info[idx][:, 0])),
                                                    "height" : int(np.max(new_region_info[idx][:, 1]) - np.min(new_region_info[idx][:, 1]))
                                                    }  
                regions.append(region)
            return_data["regions"] = regions
            return_data["file_attributes"] = {}
            total_data[os.path.basename(file_name)] = return_data
        return total_data

    def paste_bulr_func(self, new_rect, background_img=None):
        """
        根据原始框的位置与边界的关系，进行自动调整
        """
        # 扩大平滑范围
        center_p = [new_rect[0] + new_rect[2]//2, new_rect[1]+new_rect[3]//2]
        w= new_rect[2]
        h = new_rect[3]

        new_w = w * 1.5
        if new_w < 32:
            new_w = 48
        elif new_w > self.save_image.shape[1]:
            new_w = self.save_image.shape[1]
        
        if center_p[0] - new_w//2 > 0 and center_p[0] + new_w//2 < self.save_image.shape[1]:
            pass
        elif center_p[0] - new_w//2 < 0 and new_w < self.save_image.shape[1]:
            center_p[0] +=  new_w//2 -  center_p[0]
        elif center_p[0] + new_w//2 > self.save_image.shape[1] and new_w < self.save_image.shape[1]:
            center_p[0] -=  center_p[0] + new_w//2 - self.save_image.shape[1]
        else:
            center_p[0] = self.save_image.shape[1] // 2
            new_w = self.save_image.shape[1]
        

        new_h = h * 2
        if new_h < 32:
            new_h = 48
        elif new_h > self.save_image.shape[0]:
            new_h = self.save_image.shape[0]
        
        if center_p[1] - new_h//2 >0 and center_p[1] + new_h//2 < self.save_image.shape[0]:
            pass
        elif center_p[1] - new_h//2 < 0 and new_h < self.save_image.shape[0]:
            center_p[1] +=  new_h//2 -  center_p[1]
        elif center_p[1] + new_h//2 > self.save_image.shape[0] and new_h < self.save_image.shape[0]:
            center_p[1] -=  center_p[1] + new_h//2 - self.save_image.shape[0]
        else:
            center_p[1] = self.save_image.shape[0] // 2
            new_h = self.save_image.shape[0]

        new_rect = [ int(center_p[0] - new_w//2), int(center_p[1]-new_h//2), int(new_w), int(new_h)]

        if self.request_return_image:
            total_image = background_img
        else:
            total_image = self.save_image
        mask_background = total_image[new_rect[1]:new_rect[1] + new_rect[3], 
                    new_rect[0]:new_rect[0] + new_rect[2]]
        new_mask_background = imgaug_tool.aug_image_smoothing_3(mask_background)
        return  new_mask_background, new_rect

    def random_add_region(self, image, label,add_line=False, 
            polygon=None, mask=None,copy_mask=None, copy_pts=None, 
            use_image_as_mask=False, enlarge_mask=False,fill_all_row=False, 
            paste_bulr=False):
        """
        @label: 标签. `list` or `str`
            如果类型为`list`则为多标签`many_polygon`
        @enlarge_mask: `bool`
            是否增大`mask`区域, 避免两个`mask`距离太近或重叠情况
        @use_image_as_mask: `bool`
            直接使用图片作为`mask`
        """
        
        many_polygon = False
        if type(label) == list:
            many_polygon = True
            
        if polygon is not None and mask is not None :
            mask_big = mask
        elif polygon is not None :
            mask_big = np.zeros(image.shape[:2], dtype=np.uint8)
            mask_big = cv2.fillConvexPoly(mask_big,  polygon , [255])
        elif mask is not None :
            mask_big = mask
        else:
            raise NotImplementedError
        
        new_rect  = self._get_random_rect(mask_big ,add_line)
        if new_rect is None:
            # print("can't find a rect")
            return False

        crop_image = None
        crop_image_diff = new_rect[:2]
        if self.request_return_image:
            copy_image = copy.copy(self.ori_image)
            mask_background = copy_image[new_rect[1]:new_rect[1] + new_rect[3], 
                                    new_rect[0]:new_rect[0] + new_rect[2]]
            cv2.copyTo(image, mask_big, mask_background)
            if paste_bulr:
                new_mask_background, new_blur_rect = self.paste_bulr_func(new_rect, copy_image)

                copy_image[new_blur_rect[1]:new_blur_rect[1] + new_blur_rect[3], 
                                    new_blur_rect[0]:new_blur_rect[0] + new_blur_rect[2]] = new_mask_background
            ## random crop
            h ,w = copy_image.shape[:2]
            x,y,w,h,l = opencv_tool._random_gen_crop_rect(new_rect + label, [h, w], h * 2// 3, w *2//3, min_wh=416 )
            if x is None:return False
            crop_image = copy_image[y:y+h, x:x+w]
            new_rect = [x,y,w,h]
        else:
            
            mask_background = self.save_image[new_rect[1]:new_rect[1] + new_rect[3], 
                                    new_rect[0]:new_rect[0] + new_rect[2]]
            mask_front = image.copy()
            cv2.copyTo(mask_front, mask_big, mask_background)

            if paste_bulr:
                new_mask_background, new_blur_rect = self.paste_bulr_func(new_rect)

                self.save_image[new_blur_rect[1]:new_blur_rect[1] + new_blur_rect[3], 
                                    new_blur_rect[0]:new_blur_rect[0] + new_blur_rect[2]] = new_mask_background
                
        # update
        offset_x =  crop_image_diff[0] 
        offset_y =  crop_image_diff[1]
        if many_polygon:
            label_region = np.array(polygon) + np.array([offset_x, offset_y])
            
        elif polygon is not None :
            label_region = [np.array(polygon) + np.array([offset_x, offset_y])]
            label = [label]

        elif mask is not None :
            h,w = mask.shape[:2]
            p1 = [0 + offset_x, 0 + offset_y]
            p2 = [w + offset_x, 0 + offset_y]
            p3 = [w + offset_x, h + offset_y]
            p4 = [0 + offset_x, h + offset_y]
            label_region = [np.array([p1,p2,p3,p4])]
        if label is None:
            label = [label]

        mask_region = None
        if use_image_as_mask:
            mask_region = np.array([[new_rect[0], new_rect[1]],
                                [new_rect[0]+ new_rect[2], new_rect[1]],
                                [new_rect[0]+ new_rect[2], new_rect[1]+new_rect[3]],
                                [new_rect[0], new_rect[1]+new_rect[3]]])
        self._update_data(label, label_region, mask_region=mask_region, 
                        crop_image=crop_image, enlarge_mask=enlarge_mask, 
                        init_data=False,
                        fill_all_row=fill_all_row)

        return True

    def _get_random_rect(self, mask_small,add_line=False, small_flag=False, over_lap=0.002, find_times=50, fast_find=True):
        """
        
        @find_times: 查找 `50` 次
            sss 
        @fast_find: 快速查找 
            慢速查找时通过两二值图像相与, 快速查找时直接判断图像`mask`区域是否为空白
            未实现...
        """

        height, width = self.ori_image.shape[:2]
        mask_height, mask_width = mask_small.shape[:2]
        # print(mask_height, mask_width)

        choice_y = [x for x in range(5,height-mask_height-5, 3)]
        choice_x = [x for x in range(5,width-mask_width-5, 3)]
        if len(choice_x) == 0 or len(choice_y) == 0:
            return None
        # print("add_line: ", add_line)

        count = 0
        new_rect = None
        consum_h = 10
        while count < find_times:
            count += 1
            if len(choice_x) == 0 or len(choice_y) == 0:return None

            if add_line:
                tmp_y = min(self.line_height + consum_h, height-mask_height-5)
                consum_h += 2
            else: 
                tmp_y = choice_y[np.random.randint(len(choice_y))]
            tmp_x = choice_x[np.random.randint(len(choice_x))]
            # print(self.line_height, tmp_x, tmp_y)

            ori_mask = self.all_poly_mask[tmp_y:tmp_y+mask_height, tmp_x:tmp_x+mask_width]
            
            if np.sum(ori_mask) / 255*(mask_height * mask_width) < over_lap:
                new_rect = [tmp_x, tmp_y, mask_width, mask_height]

                if add_line:
                    self.line_height = tmp_y + mask_height
                break

        return new_rect

    def _update_data(self, label, label_region, init_data=False, 
            crop_image=None,  mask_region=None,
            enlarge_mask=False, fill_all_row=False):
        """
        @label: `list`
            list
        @label_region: `list`
            list
        @mask_region: `None`
            如果为`True`, 则 `fill_all_row` 无效
        @enlarge_mask: `None`
            如果为`True`, 则以`mask_region`或`label_region`作为扩充依据
        @fill_all_row: `None`
            如果为`True`, 则以`label_region`作为 横向延伸
        """

        for l,r in zip(label, label_region):
            if self.request_return_image and init_data:
                ## 在初始化时 将已有的抹掉
                whole_mask = np.zeros(self.ori_image.shape[:2], dtype=np.uint8)
                paste_image = np.zeros(self.ori_image.shape, dtype=np.uint8)
                new_mask = cv2.fillConvexPoly(whole_mask, np.array(r), [255])
                if enlarge_mask:
                    kernel = cv2.getStructuringElement(cv2.MORPH_RECT, 
                        (np.max(self.ori_image.shape[:2]) // 10, 
                            np.max(self.ori_image.shape[:2]) // 10))  # 矩形结构
                    new_mask = cv2.dilate(new_mask, kernel)
                mean_value = np.mean(self.ori_image, axis=(0,1))
                paste_image[:,:] = mean_value
                self.ori_image = cv2.copyTo(paste_image, new_mask, self.ori_image)
            else:
                self.label_info.append(l)
                self.region_info.append(r)
                self.object_count+=1

            if self.request_return_image and not init_data:
                self.crop_images.append(crop_image)
                continue                    ## 只添加 r l img 不改动 all_poly_mask 

            if mask_region is not None:
                if enlarge_mask:
                    enlarge_region = opencv_tool.enlarge_contours_border(mask_region, region_type="polygon", border_shape=self.ori_image.shape[:2])
                else:
                    enlarge_region = mask_region
            elif fill_all_row:
                # # 将整行抹掉
                new_region = sorted(r, key=lambda x : x[1])
                min_y = new_region[0][1]
                max_y = new_region[-1][1]
                enlarge_region = [[0, min_y],[self.ori_image.shape[1], min_y],[self.ori_image.shape[1], max_y],[0, max_y]]

            elif enlarge_mask:
                enlarge_region = opencv_tool.enlarge_contours_border(r, region_type="polygon", border_shape=self.ori_image.shape[:2], dilate_ratio=1.8)
            else:
                enlarge_region = r
            
            self.all_poly_mask = cv2.fillConvexPoly(self.all_poly_mask, enlarge_region, [255])
        

class CRNNPlateEnhance:

    def __init__(self, cv_image,enlarge_mask=False, data_dict=None, flag="polygon",fill_all_row=False):
        self.object_count = 0
        self.label_info = []
        self.region_info = []
        self.polygon_flag = flag

        self.ori_image = copy.copy(cv_image)
        self.save_image = copy.copy(cv_image)
        self.all_poly_mask = np.zeros(self.ori_image.shape[:2], dtype=np.uint8)
        self._load_data(data_dict, enlarge_mask=enlarge_mask, fill_all_row=fill_all_row)
        self.line_height = np.random.randint(20)

        self.save_images = []
        self.save_labels = []

    def _load_data(self, data_dict, enlarge_mask=False, fill_all_row=False):
        if data_dict is None :
            return

        if self.polygon_flag == "polygon":
            xys = via_tool.read_via_poloygon_to_list_imp(data_dict["regions"])
        elif self.polygon_flag == "rect":
            xys = via_tool.read_via_rect_to_point_imp(data_dict["regions"])
        else:
            raise NotImplementedError

        for xy, l in xys:
            if self.polygon_flag == "polygon":
                self._update_data([l], [np.array(xy)], enlarge_mask=enlarge_mask, fill_all_row=fill_all_row)
            elif self.polygon_flag == "rect":
                self._update_data([l], [np.array([
                                                    [xy[0], xy[1]],
                                                    [xy[0] + xy[2], xy[1]],
                                                    [xy[0] + xy[2], xy[1] + xy[3]],
                                                    [xy[0], xy[1] + xy[3]]
                                                ])], enlarge_mask= enlarge_mask, fill_all_row=fill_all_row)
            else:
                raise NotImplementedError

    def write_image(self,need_aug=False):
        """
        @mask: `array` or `None`
            是否增加水印
        @need_aug： `True` or `False`
            是否需要图像增强

        """


        return self.save_labels

    def random_paste_plate(self, image, label,save_path, need_aug=False):
        """

        """
        height, width = image.shape[:2]
        top = np.random.randint(int(height * 0.3))
        down = np.random.randint(int(height * 0.3))
        left = np.random.randint(int(width * 0.25))
        right = np.random.randint(int(width * 0.25))


        mask_big = np.ones((height, width), dtype=np.uint8) * 255
        mask_big = cv2.copyMakeBorder(mask_big, top, down, left, right, cv2.BORDER_CONSTANT)
        new_image = cv2.copyMakeBorder(image, top, down, left, right, cv2.BORDER_CONSTANT)

        new_rect  = self._get_random_rect(mask_big )

        if new_rect is None:
            # print("can't find a rect")
            return False

        mask_background = copy.copy(self.save_image[new_rect[1]:new_rect[1] + new_rect[3], 
                                new_rect[0]:new_rect[0] + new_rect[2]])
        mask_front = new_image.copy()
        cv2.copyTo(mask_front, mask_big, mask_background)


        ## 放射变换
        dst_width, dst_height = 256, 64
        pts2 = np.float32([[0,0], [dst_width, 0], [dst_width, dst_height], [0,dst_height]])
        pts1 = np.float32([
            [
                0 if left == 0 else np.random.randint(left),
                0 if top == 0 else np.random.randint(top)

            ],
            [
                width + left if right == 0 else width + left + np.random.randint(right),
                0 if top == 0 else np.random.randint(top)
            ],
            [
                width + left if right == 0 else width + left + np.random.randint(right),
                height + top if down == 0 else  height + top + np.random.randint(down)
            ],
            [
                0 if left == 0 else np.random.randint(left),
                height + top if down == 0 else  height + top + np.random.randint(down)
            ]
            ])


        M  = cv2.getPerspectiveTransform(pts1,pts2)

        dst = cv2.warpPerspective(mask_background,M,(dst_width, dst_height))


        if need_aug:
            new_image = imgaug_tool.aug_image_smoothing_2(dst)
        else:
            new_image = dst

        gray_image = cv2.cvtColor(new_image, cv2.COLOR_BGR2GRAY)
        cv2.imwrite(save_path, gray_image, [cv2.IMWRITE_JPEG_QUALITY, np.random.randint(65,95)])
        

        self.save_labels.append((os.path.basename(save_path), label))

        return True

    def _get_random_rect(self, mask_small,add_line=False, small_flag=False, over_lap=0.002, find_times=50, fast_find=True):
        """
        
        @find_times: 查找 `50` 次
            sss 
        @fast_find: 快速查找 
            慢速查找时通过两二值图像相与, 快速查找时直接判断图像`mask`区域是否为空白
            未实现...
        """

        height, width = self.ori_image.shape[:2]
        mask_height, mask_width = mask_small.shape[:2]
        # print(mask_height, mask_width)

        choice_y = [x for x in range(5,height-mask_height-5, 3)]
        choice_x = [x for x in range(5,width-mask_width-5, 3)]
        if len(choice_x) == 0 or len(choice_y) == 0:
            return None
        # print("add_line: ", add_line)

        count = 0
        new_rect = None
        consum_h = 10
        while count < find_times:
            count += 1
            if len(choice_x) == 0 or len(choice_y) == 0:return None

            if add_line:
                tmp_y = min(self.line_height + consum_h, height-mask_height-5)
                consum_h += 2
            else: 
                tmp_y = choice_y[np.random.randint(len(choice_y))]
            tmp_x = choice_x[np.random.randint(len(choice_x))]
            # print(self.line_height, tmp_x, tmp_y)

            ori_mask = self.all_poly_mask[tmp_y:tmp_y+mask_height, tmp_x:tmp_x+mask_width]
            
            if np.sum(ori_mask) / 255*(mask_height * mask_width) < over_lap:
                new_rect = [tmp_x, tmp_y, mask_width, mask_height]

                if add_line:
                    self.line_height = tmp_y + mask_height
                break

        return new_rect

    def get_whole_mask(self, tmp_x, tmp_y, mask_height, mask_width, std_mask):
        whole_mask = np.zeros(self.ori_image.shape[:2], dtype=np.uint8)

        for region in self.region_info:
            new_mask = np.zeros(self.ori_image.shape[:2], dtype=np.uint8)
            # print("new_mask.shape: ", new_mask.shape)
            # print("region: ", region)
            enlarge_region = opencv_tool.enlarge_contours_border(region, region_type="rect", border_shape=self.ori_image.shape[:2])
            new_mask = cv2.fillConvexPoly(new_mask, np.array(enlarge_region), [255])
            out_mask = cv2.bitwise_and(std_mask, new_mask)
            if np.sum(out_mask) > 2:
                whole_mask = cv2.fillConvexPoly(whole_mask, np.array(enlarge_region), [255])
        
        return whole_mask

    def _update_data(self, label, label_region, mask_region=None,enlarge_mask=False, fill_all_row=False):
        """
        @label: `list`
            list
        @label_region: `list`
            list
        @mask_region: `None`
            如果为`True`, 则 `fill_all_row` 无效
        @enlarge_mask: `None`
            如果为`True`, 则以`mask_region`或`label_region`作为扩充依据
        @fill_all_row: `None`
            如果为`True`, 则以`label_region`作为 横向延伸
        """
        for l,r in zip(label, label_region):
            self.label_info.append(l)
            self.region_info.append(r)
            self.object_count+=1
            if mask_region is not None  :
                continue
            
            if fill_all_row:
                # # 将整行抹掉
                new_region = sorted(r, key=lambda x : x[1])
                min_y = new_region[0][1]
                max_y = new_region[-1][1]
                r = [[0, min_y],[self.ori_image.shape[1], min_y],[self.ori_image.shape[1], max_y],[0, max_y]]


            if enlarge_mask:
                enlarge_region = opencv_tool.enlarge_contours_border(r, region_type="polygon", border_shape=self.ori_image.shape[:2])
            else:
                enlarge_region = r
            
            self.all_poly_mask = cv2.fillConvexPoly(self.all_poly_mask, enlarge_region, [255])
            # cv2.imwrite(str(self.object_count) + "_all_poly_mask.jpg", self.all_poly_mask)
        
        if mask_region  is not None :

            if enlarge_mask:
                enlarge_region = opencv_tool.enlarge_contours_border(mask_region, region_type="polygon", border_shape=self.ori_image.shape[:2])
            else:
                enlarge_region = mask_region
            self.all_poly_mask = cv2.fillConvexPoly(self.all_poly_mask, enlarge_region, [255])
            # cv2.imwrite(str(self.object_count) + "_all_poly_mask.jpg", self.all_poly_mask)

    def warp_perspective(self, img,max_x_ratio=0.55, max_y_ratio=0.4, max_h_ratio=0.2):
        """ 使图像轻微的畸变
            img 输入图像
            factor 畸变的参数
            size 为图片的目标尺寸
        """
        size_o = [img.shape[1],img.shape[0]]

        pts1 = np.float32([[0,0],[size_o[0],0],[size_o[0],size_o[1]],[0,size_o[1]]])
        
        # 车牌整体水平偏移, update ->  只会变短
        prob = list(np.arange(100)) + list(np.arange(60,100))  + list(np.arange(80,100))
        prob_choice  = np.random.choice(prob)
        # # 车牌右上 右下向左边收缩的偏移
        x_diff = int(float(size_o[0] * prob_choice)* 0.01 *max_x_ratio )
        # # 车牌右上 右下向上边抬的偏移
        y_diff = int(float(size_o[1] * prob_choice )* 0.01  *max_y_ratio )
        # # 车牌左上和右上点 左右摇摆的 偏移
        h_diff = int(float(size_o[1] * prob_choice )* 0.01  *max_h_ratio ) # int(size_o[0]* 0.1) # np.random.randint(int(img.shape[1]* 0.1))
        # 右下点往上抬的偏移
        v_diff = np.random.randint(int(size_o[1]* 0.1), int(size_o[1]* 0.25))

        # 去掉改左边的变换
        if False:
            # change left
            # x_diff = -x_diff if np.random.randint(2) < 1 else x_diff
            # y_diff = -y_diff if np.random.randint(2) < 1 else y_diff
            x_diff = x_diff
            y_diff = -y_diff
            # 水平偏移
            h_diff = np.random.randint(int(img.shape[1]* 0.05))
            if np.random.randint(2) < 1: h_diff = -h_diff

            p1 = [
                    0 ,
                    0 if y_diff < 0 else y_diff]
            p2 = [
                size_o[0]-x_diff+h_diff if x_diff < 0 else size_o[0]-x_diff+h_diff,
                  -y_diff  if y_diff < 0  else 0]
            p3 = [
                size_o[0]-x_diff if x_diff < 0 else size_o[0]-x_diff,
                size_o[1]-y_diff  if y_diff < 0  else size_o[1]
            ]
            # 竖直偏移
            v_diff = np.random.randint(int(img.shape[1]* 0.05))
            p4 =[
                0,
                0 + size_o[1]- v_diff if y_diff < 0 else y_diff + size_o[1] - v_diff
            ]
            pts2 = np.float32([p1,p2,p3,p4])
        else:
            # change right
            x_diff = -x_diff
            y_diff = -y_diff

            if np.random.randint(2) < 1: h_diff = -h_diff

            p1 = [
                    0 if h_diff < 0 else h_diff, 
                    -y_diff if y_diff < 0 else 0]
            p2 = [
                    size_o[0]+x_diff if h_diff < 0 else size_o[0]+x_diff+h_diff,
                    0  if y_diff < 0  else y_diff
                  ]
            p3 = [
                size_o[0]+x_diff-h_diff  if h_diff < 0 else size_o[0]+x_diff,
                  size_o[1] - v_diff if y_diff < 0  else size_o[1] +y_diff- v_diff 
            ]
            p4 =[
                -h_diff if h_diff < 0 else 0, 
                size_o[1] -y_diff if y_diff < 0 else  size_o[1]
            ]
            pts2 = np.float32([p1,p2,p3,p4])

        M  = cv2.getPerspectiveTransform(pts1,pts2)
        max_x ,max_y= np.max(pts2,axis=0 )

        dst = cv2.warpPerspective(img,M,(max_x, max_y))

        return dst, pts2

